/** file Note.cpp
    author belot.nicolas
*/

#include "Note.h"
#include <cmath>
namespace libtrckr {

unsigned short Note::_bpm=120;
unsigned short Note::_mesure=4;
unsigned int Note::_bitrate=44100;

const float Note::keyFreq[10][21]={
		{Cb0,C_0,Cd0,Db0,D_0,Dd0,Eb0,E_0,Fb0,Ed0,F_0,Fd0,Gb0,G_0,Gd0,Ab0,A_0,Ad0,Bb0,B_0,Bd0},
		{Cb1,C_1,Cd1,Db1,D_1,Dd1,Eb1,E_1,Fb1,Ed1,F_1,Fd1,Gb1,G_1,Gd1,Ab1,A_1,Ad1,Bb1,B_1,Bd1},
		{Cb2,C_2,Cd2,Db2,D_2,Dd2,Eb2,E_2,Fb2,Ed2,F_2,Fd2,Gb2,G_2,Gd2,Ab2,A_2,Ad2,Bb2,B_2,Bd2},
		{Cb3,C_3,Cd3,Db3,D_3,Dd3,Eb3,E_3,Fb3,Ed3,F_3,Fd3,Gb3,G_3,Gd3,Ab3,A_3,Ad3,Bb3,B_3,Bd3},
		{Cb4,C_4,Cd4,Db4,D_4,Dd4,Eb4,E_4,Fb4,Ed4,F_4,Fd4,Gb4,G_4,Gd4,Ab4,A_4,Ad4,Bb4,B_4,Bd4},
		{Cb5,C_5,Cd5,Db5,D_5,Dd5,Eb5,E_5,Fb5,Ed5,F_5,Fd5,Gb5,G_5,Gd5,Ab5,A_5,Ad5,Bb5,B_5,Bd5},
		{Cb6,C_6,Cd6,Db6,D_6,Dd6,Eb6,E_6,Fb6,Ed6,F_6,Fd6,Gb6,G_6,Gd6,Ab6,A_6,Ad6,Bb6,B_6,Bd6},
		{Cb7,C_7,Cd7,Db7,D_7,Dd7,Eb7,E_7,Fb7,Ed7,F_7,Fd7,Gb7,G_7,Gd7,Ab7,A_7,Ad7,Bb7,B_7,Bd7},
		{Cb8,C_8,Cd8,Db8,D_8,Dd8,Eb8,E_8,Fb8,Ed8,F_8,Fd8,Gb8,G_8,Gd8,Ab8,A_8,Ad8,Bb8,B_8,Bd8},
		{Cb9,C_9,Cd9,Db9,D_9,Dd9,Eb9,E_9,Fb9,Ed9,F_9,Fd9,Gb9,G_9,Gd9,Ab9,A_9,Ad9,Bb9,B_9,Bd9}
	};

const std::string Note::keyName[10][21]={
		{"Cb0","C-0","C#0","Db0","D-0","D#0","Eb0","E-0","Fb0","E#0","F-0","F#0","Gb0","G-0","G#0","Ab0","A-0","A#0","Bb0","B_0","B#0"},
		{"Cb1","C-1","C#1","Db1","D-1","D#1","Eb1","E-1","Fb1","E#1","F-1","F#1","Gb1","G-1","G#1","Ab1","A-1","A#1","Bb1","B_1","B#1"},
		{"Cb2","C-2","C#2","Db2","D-2","D#2","Eb2","E-2","Fb2","E#2","F-2","F#2","Gb2","G-2","G#2","Ab2","A-2","A#2","Bb2","B_2","B#2"},
		{"Cb3","C-3","C#3","Db3","D-3","D#3","Eb3","E-3","Fb3","E#3","F-3","F#3","Gb3","G-3","G#3","Ab3","A-3","A#3","Bb3","B_3","B#3"},
		{"Cb4","C-4","C#4","Db4","D-4","D#4","Eb4","E-4","Fb4","E#4","F-4","F#4","Gb4","G-4","G#4","Ab4","A-4","A#4","Bb4","B_4","B#4"},
		{"Cb5","C-5","C#5","Db5","D-5","D#5","Eb5","E-5","Fb5","E#5","F-5","F#5","Gb5","G-5","G#5","Ab5","A-5","A#5","Bb5","B_5","B#5"},
		{"Cb6","C-6","C#6","Db6","D-6","D#6","Eb6","E-6","Fb6","E#6","F-6","F#6","Gb6","G-6","G#6","Ab6","A-6","A#6","Bb6","B_6","B#6"},
		{"Cb7","C-7","C#7","Db7","D-7","D#7","Eb7","E-7","Fb7","E#7","F-7","F#7","Gb7","G-7","G#7","Ab7","A-7","A#7","Bb7","B_7","B#7"},
		{"Cb8","C-8","C#8","Db8","D-8","D#8","Eb8","E-8","Fb8","E#8","F-8","F#8","Gb8","G-8","G#8","Ab8","A-8","A#8","Bb8","B_8","B#8"},
		{"Cb9","C-9","C#9","Db9","D-9","D#9","Eb9","E-9","Fb9","E#9","F-9","F#9","Gb9","G-9","G#9","Ab9","A-9","A#9","Bb9","B_9","B#9"}
	};

Duration::Duration(note_duration_t d){
	length=1/ pow(2, d);
}

Duration::Duration(const Duration& d){
	length=d.length;
}

void Duration::operator=(const Duration& d){
	length=d.length;
}

float Duration::getLength() const{
	return length;
}

Duration Duration::operator+(const Duration& d){
	Duration ret(*this);
	ret+=d;
	return ret;
}

void Duration::operator+=(const Duration& d){
	length+=d.length;
}

Note::Note(){
	_name="A_5";
	freq=keyFreq[4][16];
	len= Duration(Duration::NOIRE);
}
Note::Note(const Note& n):_name(n._name),freq(n.freq),len(n.len),pointed(n.pointed){

}
Note::Note(std::string& name, Duration::note_duration_t dur=Duration::NOIRE, bool point=false){
	_name=name;
	if(name=="blank"){
		freq=0;
	}else{
	for(uint i=0;i<10;i++){
		for(uint j=0;j<21;j++){
			if(name==keyName[i][j]){
				freq=keyFreq[i][j];
			}
		}
	}
	}
	len=Duration(dur);
	pointed=point;

}

Note::Note(std::string& name, Duration& dur, bool point=false){
	_name=name;
	if(name=="blank"){
		freq=0;
	}else{
	for(uint i=0;i<10;i++){
		for(uint j=0;j<21;j++){
			if(name==keyName[i][j]){
				freq=keyFreq[i][j];
			}
		}
	}
	}
	len=dur;
	pointed=point;

}

Note::Note(uint semitone, uint octave, Duration::note_duration_t dur, bool point){
	_name=std::string(semitone + " " + octave);
	if(semitone==0){
		freq==keyFreq[octave][1];
	}else if(semitone==1){
		freq=keyFreq[octave][2];
	}else if(semitone==2){
		freq=keyFreq[octave][4];
	}else if(semitone==3){
		freq=keyFreq[octave][5];
	}else if(semitone==4){
		freq=keyFreq[octave][7];
	}else if(semitone==5){
		freq=keyFreq[octave][10];
	}else if(semitone==6){
		freq=keyFreq[octave][11];
	}else if(semitone==7){
		freq=keyFreq[octave][13];
	}else if(semitone==8){
		freq=keyFreq[octave][14];
	}else if(semitone==9){
		freq=keyFreq[octave][15];
	}else if(semitone==10){
		freq=keyFreq[octave][17];
	}else if(semitone==11){
		freq=keyFreq[octave][18];
	}else if(semitone==12){
		freq=keyFreq[octave][20];
	}
	len=Duration(dur);
	pointed=point;

}

double Note::duration() const{
	//how many seconds last a note;
	float mult=pointed?1.5:1.0;
	return mult *( ( 60.0/_bpm)  * _mesure * len.getLength() ) ;

}
std::string Note::name() const {
	return _name;
}
uint   Note::sampleLength() const{
	//how many samples last a note;
	return duration()*_bitrate;
}
float Note::getLength() const {
	float mult=pointed?1.5:1.0;
	return mult * len.getLength();
}
float Note::frequency() const{
	return freq;
}

unsigned short Note::bpm() {
	return _bpm;
}

void Note::bpm(unsigned short val) {
	_bpm=val;
}

unsigned short Note::mesure(){
	return _mesure;
}

void Note::mesure(unsigned short val){
	_mesure=val;
}


unsigned int Note::bitrate()  {
	return _bitrate;
}

void Note::bitrate(unsigned int val) {
	_bitrate=val;
}


}




